package com.sc.byahi.user.client;

import static com.sc.byahi.user.client.UIUtil.ftInStringToInches;
import static com.sc.byahi.user.client.UIUtil.getCBText;
import static com.sc.byahi.user.client.UIUtil.getChkText;
import static com.sc.byahi.user.client.UIUtil.inchesToFtInString;
import static com.sc.byahi.user.client.UIUtil.setListValue;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.Date;
import java.util.List;
import java.util.logging.Logger;

import com.google.gwt.core.client.JsArray;
import com.google.gwt.core.client.JsArrayString;
import com.google.gwt.event.dom.client.ChangeEvent;
import com.google.gwt.event.dom.client.ChangeHandler;
import com.google.gwt.event.dom.client.ClickEvent;
import com.google.gwt.event.dom.client.ClickHandler;
import com.google.gwt.event.dom.client.KeyPressEvent;
import com.google.gwt.event.dom.client.KeyPressHandler;
import com.google.gwt.i18n.client.DateTimeFormat;
import com.google.gwt.user.client.History;
import com.google.gwt.user.client.rpc.AsyncCallback;
import com.google.gwt.user.client.ui.Button;
import com.google.gwt.user.client.ui.CheckBox;
import com.google.gwt.user.client.ui.Composite;
import com.google.gwt.user.client.ui.FlexTable;
import com.google.gwt.user.client.ui.FlowPanel;
import com.google.gwt.user.client.ui.HTML;
import com.google.gwt.user.client.ui.Hidden;
import com.google.gwt.user.client.ui.HorizontalPanel;
import com.google.gwt.user.client.ui.Image;
import com.google.gwt.user.client.ui.Label;
import com.google.gwt.user.client.ui.ListBox;
import com.google.gwt.user.client.ui.MultiWordSuggestOracle;
import com.google.gwt.user.client.ui.RadioButton;
import com.google.gwt.user.client.ui.SimplePanel;
import com.google.gwt.user.client.ui.SuggestBox;
import com.google.gwt.user.client.ui.TextArea;
import com.google.gwt.user.client.ui.TextBox;
import com.google.gwt.user.client.ui.VerticalPanel;
import com.google.gwt.user.client.ui.Widget;
import com.google.gwt.user.datepicker.client.DateBox;
import com.sc.byahi.user.client.components.HistoryTokens;
import com.sc.byahi.user.client.components.SuggestSelectionList;
import com.sc.byahi.user.client.components.maps.InfoWindow;
import com.sc.byahi.user.client.components.maps.LatLng;
import com.sc.byahi.user.client.components.maps.MClickEvent;
import com.sc.byahi.user.client.components.maps.MClickHandler;
import com.sc.byahi.user.client.components.maps.MDragEndEvent;
import com.sc.byahi.user.client.components.maps.MDragEndHandler;
import com.sc.byahi.user.client.components.maps.MapOptions;
import com.sc.byahi.user.client.components.maps.MapWidget;
import com.sc.byahi.user.client.components.maps.Marker;
import com.sc.byahi.user.client.components.maps.MarkerOptions;
import com.sc.byahi.user.client.components.maps.places.Autocomplete;
import com.sc.byahi.user.client.components.maps.places.AutocompleteOptions;
import com.sc.byahi.user.client.components.maps.places.PlaceChangeMapEvent;
import com.sc.byahi.user.client.components.maps.places.PlaceChangeMapHandler;
import com.sc.byahi.user.client.components.maps.places.PlaceGeometry;
import com.sc.byahi.user.client.components.maps.places.PlaceResult;
import com.sc.byahi.user.client.components.maps.services.Geocoder;
import com.sc.byahi.user.client.components.maps.services.GeocoderAddressComponent;
import com.sc.byahi.user.client.components.maps.services.GeocoderRequest;
import com.sc.byahi.user.client.components.maps.services.GeocoderRequestHandler;
import com.sc.byahi.user.client.components.maps.services.GeocoderResult;
import com.sc.byahi.user.client.components.maps.services.GeocoderStatus;
import com.sc.byahi.user.shared.Profile;
import com.sc.byahi.user.shared.constants.Config;
import com.sc.byahi.user.shared.constants.Lists;

public class ProfileUpdateView extends Composite {
	private Logger logger = Logger.getLogger("com.sc.byahi.user.client.ProfileUpdateView");
	HorizontalPanel main = new HorizontalPanel();
	VerticalPanel v1 = new VerticalPanel();
	VerticalPanel v2 = new VerticalPanel();
	// ScrollPanel scrollPanel = new ScrollPanel();
	FlexTable ft = new FlexTable();
	private final Hidden hidden = new Hidden();
	private final Label lblName = new Label("Full Name");
	private final TextBox txtName = new TextBox();
	private final Label lblGender = new Label("Gender");
	private final RadioButton rdbtnMale = new RadioButton("gender", "Male");
	private final RadioButton rdbtnFemale = new RadioButton("gender", "Female");
	private final Label lblDateOfBirth = new Label("Date of birth (dd/mm/yyyy)");
	private final DateBox txtDateBox = new DateBox();

	private final Label lblMaritalStatus = new Label("Marital status");
	private final ListBox cbMaritalStatus = new ListBox();
	private final Label lblMaritalStatusChildren = new Label("Children");;
	private final ListBox cbMaritalStatusChildren = new ListBox();
	private final Label lblHeight = new Label("Height");
	private final ListBox cbHeight = new ListBox();
	private final Label lblDegrees = new Label("Education/Degrees");
	// private final SelectionList slDegreeList = new SelectionList();
	private final SuggestSelectionList slDegreeList = new SuggestSelectionList(UIUtil.lists.get(Lists.DEGREES).get(""));
	private final Label lblMotherTongue = new Label("Mother tongue");
	private final ListBox cbMotherTongue = new ListBox();
	private final Label lblLanguages = new Label("Other languages");
	// private final SelectionList slLanguageList = new SelectionList();
	private final SuggestSelectionList slLanguageList = new SuggestSelectionList(UIUtil.lists.get(Lists.MOTHER_TONGUE).get(""));
	private final Label lblReligion = new Label("Religion");
	private final ListBox cbReligion = new ListBox();
	private final Label lblCaste = new Label("Caste");
	private final SuggestBox casteSuggestBox;
	private final Label lblPhysicalStatus = new Label("Physical status");
	private final ListBox cbPhysicalStatus = new ListBox();
	private final Label lblPhysicalStatusDetail = new Label("Disability description");;
	private final ListBox cbPhysicalStatusDetail = new ListBox();
	private final Image imgPhysicalStatusDetail = new Image();
	private final Label lblBloodgroup = new Label("Blood group");
	private final ListBox cbBloodGroup = new ListBox();
	private final Label lblAboutMe = new Label("About me");
	private final TextArea txtAboutMe = new TextArea();
	private final String aboutMeExplStr = "Please write something about yourself, your expectations and anything else you would want to write. Write at least 100 characters.";
	private final HTML aboutMeExpl = new HTML(aboutMeExplStr);
	private final Label lblEatingHabits = new Label("Eating habits");
	private final ListBox cbEatingHabits = new ListBox();
	private final Label lblManglik = new Label("Manglik");
	private final CheckBox chkManglik = new CheckBox();
	private final Label lblSmoking = new Label("Smoking");
	private final CheckBox chkSmoking = new CheckBox();
	private final Label lblEmploymentType = new Label("Employment type");
	private final ListBox cbEmploymentTypeList = new ListBox();

	private final String locationExplStr = "Please specify you approximate address. DO NOT, repeat, DO NOT, specify your exact address, for your own safety. "
			+ "Specify it like, 'Char Minar, Hyderabad' but not like 'Flat no. 25, Satyam Apt, Char Minar, Hyderabad'.";
	// private final HTML locationExpl = new HTML(locationExplStr);
	private final String locationExplStr1 = "After entering the approximate location, press enter. You will see a pointer on map, you can drag and move it if you like to change position, in the end, select one address from the list shown in pointer window.";
	// private final HTML locationExpl1 = new HTML(locationExplStr1);
	private final HTML locationExpl2 = new HTML(locationExplStr + "</br>" + locationExplStr1);

	private final Label lblCurrLocation = new Label("Current location");
	private final TextArea txtCurrAddress = new TextArea();
	private Autocomplete autoComplete = Autocomplete.newInstance(txtCurrAddress.getElement(), AutocompleteOptions.newInstance());

	@Deprecated
	private final Button btnShowCurrAddress = new Button("Show above address on map");

	private final Label lblFamilyLivingWithMe = new Label("Joint family");
	private final CheckBox chkFamilyLivingWithMe = new CheckBox();

	/**
	 * Profile currently being displayed
	 */
	private Profile currProfile = null;
	private final Button saveButton = new Button("Save");
	private final Button cancelButton = new Button("Cancel");

	private SimplePanel simpleMapHolderPanel = new SimplePanel();
	private MapWidget map;
	private Marker marker = null;

	/**
	 * This method must be called for attaching map. This method can be called only after initialization has been done.
	 */
	public void attachMap() {
		// MapHelper.createAndAttachMap(map, simpleMapHolderPanel, "750px", "500px");
		createAndAttachMap();
	}

	private void createAndAttachMap() {
		if (map == null) {
			MapOptions mapOptions = MapOptions.newInstance();
			mapOptions.setZoom(MapHelper.DEFAULT_ZOOM);
			mapOptions.setMapTypeId("ROADMAP");
			map = new MapWidget(mapOptions);
			map.getJso().setCenter(MapHelper.DEFAULT);
			map.setSize("670px", "800px");
		} else {
			map.getJso().setZoom(MapHelper.DEFAULT_ZOOM);
			map.getJso().setCenter(MapHelper.DEFAULT);
		}
		simpleMapHolderPanel.clear();
		simpleMapHolderPanel.add(map);
		autoComplete.bindTo(map.getJso());

		autoComplete.addPlaceCHangeHandler(new PlaceChangeMapHandler() {

			@Override
			public void onEvent(PlaceChangeMapEvent event) {
				PlaceResult result = autoComplete.getPlace();

				PlaceGeometry geomtry = result.getGeometry();
				if (geomtry != null) {
					LatLng center = geomtry.getLocation();
					if (geomtry.getViewPort() != null) {
						map.getJso().fitBounds(geomtry.getViewPort());
						center = geomtry.getViewPort().getCenter();
					} else {
						map.getJso().setCenter(center);
						map.getJso().setZoom(16);
					}
					createMarker(center);
					setLatLongInProfile(center);
				} else {
					showAddressNotFoundDialog();
				}
			}
		});
		map.triggerResize();
	}

	/**
	 * @wbp.parser.constructor
	 */
	public ProfileUpdateView() {
		initWidget(main);
		setStyleName("profile-update-top");
		// scrollPanel.add(main);
		main.add(v1);
		main.add(v2);

		ft.getColumnFormatter().setWidth(0, "200px");
		// ft.getColumnFormatter().setWidth(1, "570px");
		ft.getColumnFormatter().setStyleName(0, "right-align");
		int r = 0;

		ft.setWidget(r++, 0, hidden);

		ft.setWidget(r, 0, lblName);
		ft.setWidget(r++, 1, txtName);

		ft.setWidget(r, 0, lblGender);
		FlowPanel flowPanel = new FlowPanel();
		flowPanel.add(rdbtnMale);
		flowPanel.add(rdbtnFemale);
		rdbtnMale.setStyleName("radio");
		rdbtnFemale.setStyleName("radio");
		ft.setWidget(r++, 1, flowPanel);

		DateTimeFormat format = DateTimeFormat.getFormat(Config.DEFAULT_DATE_FORMAT);
		txtDateBox.setFormat(new DateBox.DefaultFormat(format));

		ft.setWidget(r, 0, lblDateOfBirth);
		ft.setWidget(r++, 1, txtDateBox);

		ft.setWidget(r, 0, lblHeight);
		ft.setWidget(r++, 1, cbHeight);

		ft.setWidget(r, 0, lblMaritalStatus);
		ft.setWidget(r++, 1, cbMaritalStatus);

		ft.setWidget(r, 0, lblMaritalStatusChildren);
		cbMaritalStatusChildren.setEnabled(false);
		ft.setWidget(r++, 1, cbMaritalStatusChildren);

		ft.setWidget(r, 0, lblReligion);
		ft.setWidget(r++, 1, cbReligion);

		ft.setWidget(r, 0, lblCaste);
		final MultiWordSuggestOracle oracleCaste = new MultiWordSuggestOracle();
		casteSuggestBox = new SuggestBox(oracleCaste);
		ft.setWidget(r++, 1, casteSuggestBox);

		ft.setWidget(r, 0, lblMotherTongue);
		ft.setWidget(r++, 1, cbMotherTongue);

		ft.setWidget(r, 0, lblLanguages);
		ft.setWidget(r++, 1, slLanguageList);

		ft.setWidget(r, 0, lblEatingHabits);
		ft.setWidget(r++, 1, cbEatingHabits);

		ft.setWidget(r, 0, lblBloodgroup);
		ft.setWidget(r++, 1, cbBloodGroup);

		ft.setWidget(r, 0, lblPhysicalStatus);
		ft.setWidget(r++, 1, cbPhysicalStatus);

		ft.setWidget(r, 0, lblPhysicalStatusDetail);
		cbPhysicalStatusDetail.setEnabled(false);
		imgPhysicalStatusDetail.setVisible(false);
		FlowPanel fp1 = new FlowPanel();
		fp1.add(cbPhysicalStatusDetail);
		fp1.add(imgPhysicalStatusDetail);
		ft.setWidget(r++, 1, fp1);

		ft.setWidget(r, 0, lblDegrees);
		ft.setWidget(r++, 1, slDegreeList);

		ft.setWidget(r, 0, lblEmploymentType);
		ft.setWidget(r++, 1, cbEmploymentTypeList);

		ft.setWidget(r, 0, lblSmoking);
		ft.setWidget(r++, 1, chkSmoking);

		ft.setWidget(r, 0, lblManglik);
		ft.setWidget(r++, 1, chkManglik);

		ft.setWidget(r, 0, lblAboutMe);
		ft.setWidget(r++, 1, aboutMeExpl);
		txtAboutMe.setStyleName("description");
		ft.setWidget(r++, 1, txtAboutMe);

		ft.setWidget(r, 0, lblCurrLocation);
		// ft.setWidget(r++, 1, locationExpl);
		// ft.setWidget(r++, 1, locationExpl1);
		ft.setWidget(r++, 1, locationExpl2);
		txtCurrAddress.setStyleName("address");
		ft.setWidget(r++, 1, txtCurrAddress);

		// enable if autocomplete doesnt work on website
		// ft.setWidget(r++, 1, btnShowCurrAddress);

		ft.setWidget(r, 0, lblFamilyLivingWithMe);
		ft.setWidget(r++, 1, chkFamilyLivingWithMe);
		// chkFamilyLivingWithMe.addClickHandler(new ClickHandler() {
		// @Override
		// public void onClick(ClickEvent event) {
		// setFamilyDetails(chkFamilyLivingWithMe.getValue());
		// }
		// });

		// ft.setWidget(r, 0, lblFamLocation);
		// txtFamAddress.setStyleName("address");
		// ft.setWidget(r++, 1, txtFamAddress);
		//
		// ft.setWidget(r++, 1, btnShowFamAddress);

		ft.setWidget(r, 0, new HTML("<p></p>"));
		ft.getFlexCellFormatter().setColSpan(r++, 0, 2);

		FlowPanel fp = new FlowPanel();
		fp.add(saveButton);
		fp.add(cancelButton);
		ft.setWidget(r++, 1, fp);
		// ft.getFlexCellFormatter().setColSpan(r++, 0, 2);

		simpleMapHolderPanel.setWidth("690px");
		simpleMapHolderPanel.setHeight("800px");

		ft.setWidget(r, 0, simpleMapHolderPanel);
		ft.getFlexCellFormatter().setColSpan(r++, 0, 2);

		v1.add(ft);

		addHandlers();
		setValues();
	}

	private void setMaritalStatusViewState() {
		String item = getCBText(cbMaritalStatus);
		if (!"Unmarried".equals(item)) {
			cbMaritalStatusChildren.setEnabled(true);
		} else {
			cbMaritalStatusChildren.setSelectedIndex(0);
			cbMaritalStatusChildren.setEnabled(false);
		}
	}

	private void setPhysicalStatusViewState() {
		String item = getCBText(cbPhysicalStatus);
		if ("Normal".equals(item)) {
			cbPhysicalStatusDetail.setEnabled(false);
		} else {
			cbPhysicalStatusDetail.setEnabled(true);
		}
		setPhysicalStatusDetailImgState();
	}

	private void setPhysicalStatusDetailImgState() {
		if (cbPhysicalStatusDetail.isEnabled()) {
			String text = getCBText(cbPhysicalStatusDetail);
			if ("Physical Disability".equals(text)) {
				imgPhysicalStatusDetail.setUrl("/images/phy_physical.png");
			}
			if ("Visual Impairment".equals(text)) {
				imgPhysicalStatusDetail.setUrl("/images/phy_visual.png");
			}
			if ("Hearing/Speech Disorder".equals(text)) {
				imgPhysicalStatusDetail.setUrl("/images/phy_vocal.png");
			}
			if ("Intellectual Disability".equals(text)) {
				imgPhysicalStatusDetail.setUrl("/images/phy_mental.png");
			}
			imgPhysicalStatusDetail.setVisible(true);
		} else {
			imgPhysicalStatusDetail.setVisible(false);
		}
	}

	private void addHandlers() {
		cbMaritalStatus.addChangeHandler(new ChangeHandler() {

			@Override
			public void onChange(ChangeEvent event) {
				setMaritalStatusViewState();
			}

		});
		cbPhysicalStatus.addChangeHandler(new ChangeHandler() {

			@Override
			public void onChange(ChangeEvent event) {
				setPhysicalStatusViewState();
			}

		});

		cbPhysicalStatusDetail.addChangeHandler(new ChangeHandler() {
			@Override
			public void onChange(ChangeEvent event) {
				setPhysicalStatusDetailImgState();
			}
		});

		cbReligion.addChangeHandler(new ChangeHandler() {

			@Override
			public void onChange(ChangeEvent event) {
				UIUtil.fillCasteSuggestList(casteSuggestBox, getCBText(cbReligion));
			}

		});
		txtAboutMe.addKeyPressHandler(new KeyPressHandler() {

			@Override
			public void onKeyPress(KeyPressEvent event) {
				aboutMeExpl.setText(getAboutMeDescText());
			}
		});

		// btnShowCurrAddress.addClickHandler(new ClickHandler() {
		//
		// @Override
		// public void onClick(ClickEvent event) {
		// showAddress(txtCurrAddress.getText());
		// }
		// });

		cancelButton.addClickHandler(new ClickHandler() {

			@Override
			public void onClick(ClickEvent event) {
				History.newItem(HistoryTokens.DASHBOARD, true);
			}
		});

		saveButton.addClickHandler(new ClickHandler() {

			@Override
			public void onClick(ClickEvent event) {
				final Profile profile = getProfile();

				if (profile != null) {
					// pobAddress.removeStyleName("invalidEntry");

					if (profile.getId() == null) {
						GreetingService.Util.getInstance().createProfile(profile, new AsyncCallback<Long>() {

							@Override
							public void onSuccess(Long result) {
								AppController.get().getOwner().getUnapporvedProfiles().add(result);
								History.newItem(HistoryTokens.MY_PROFILES, true);
								UIUtil.showDialog(Arrays.asList("Your profile ID is : " + result, "Please note down this ID."), "Profile created.");
								// AppController.get().refreshMenu();
							}

							@Override
							public void onFailure(Throwable caught) {
								UIUtil.showGenericFailureDialog();
							}
						});
					} else {
						GreetingService.Util.getInstance().updateProfile(profile, new AsyncCallback<Void>() {

							@Override
							public void onSuccess(Void result) {
								UIUtil.showDialog(
										Arrays.asList("Your profile has been updated. It will be visible for other users as soon as it is approved."),
										"Profile update");
								AppController.get().getOwner().getApprovedProfiles().remove(profile.getId());
								AppController.get().getOwner().getUnapporvedProfiles().add(profile.getId());
								History.newItem(HistoryTokens.MY_PROFILES, true);
								// AppController.get().refreshMenu();
							}

							@Override
							public void onFailure(Throwable caught) {
								UIUtil.showGenericFailureDialog();
							}
						});
					}
				}
			}
		});
	}

	private String getAboutMeDescText() {
		int diff = 450 - txtAboutMe.getText().length();
		if (diff > 0) {
			return aboutMeExplStr + diff + " characters remaining.";
		} else {
			return aboutMeExplStr + "Last " + (diff * -1) + " characters will be removed.";
		}
	}

	protected void setValues() {
		rdbtnMale.setValue(true);
		UIUtil.fillMaritalStatus(cbMaritalStatus);
		UIUtil.fillMaritalStatusChildren(cbMaritalStatusChildren);
		UIUtil.fillPhysicalStatusList(cbPhysicalStatus);
		UIUtil.fillPhysicalStatusDetailList(cbPhysicalStatusDetail);
		UIUtil.fillMothertongueList(cbMotherTongue);
		// UIUtil.fillMothertongueList(slLanguageList);
		UIUtil.fillHeightList(cbHeight, false);
		UIUtil.fillBloodGroupList(cbBloodGroup);
		UIUtil.fillDietList(cbEatingHabits);
		UIUtil.fillReligionList(cbReligion);
		UIUtil.fillCasteSuggestList(casteSuggestBox, getCBText(cbReligion));
		// UIUtil.fillDegreesList(slDegreeList);
		UIUtil.fillEmploymentTypeList(cbEmploymentTypeList);
	}

	@Deprecated
	private void showAddress(final String address) {
		GeocoderRequest request = GeocoderRequest.newInstance();
		request.setAddress(address);
		Geocoder.newInstance().geocode(request, new GeocoderRequestHandler() {

			@Override
			public void onCallback(JsArray<GeocoderResult> results, GeocoderStatus status) {
				if (status == GeocoderStatus.OK) {

					GeocoderResult location = results.get(0);
					LatLng point = location.getGeometry().getLocation();

					map.getJso().setCenter(point);
					map.getJso().setZoom(MapHelper.DEFAULT_ZOOM);

					createMarker(point);
					showPointOnMap(point);
				} else {
					UIUtil.showGenericFailureDialog();
				}
			}

		});
	}

	private void createMarker(LatLng point) {
		if (marker != null)
			marker.close();
		MarkerOptions options = MarkerOptions.getInstance();
		options.setPosition(point);
		options.setDraggable(true);
		marker = Marker.getInstance(options);
		marker.setMap(map);

		marker.addClickHandler(new MClickHandler() {
			@Override
			public void onEvent(MClickEvent event) {
				MapHelper.getInstance().createInfoWindow(map, event.getLatLng(), new HTML(txtCurrAddress.getText()));
			}
		});
		marker.addDragEndHandler(new MDragEndHandler() {

			@Override
			public void onEvent(MDragEndEvent event) {
				showPointOnMap(event.getLatLng());
			}
		});
	}

	@Deprecated
	private void createMarker1(LatLng point) {
		if (marker != null)
			marker.close();
		MarkerOptions options = MarkerOptions.getInstance();
		options.setPosition(point);
		options.setDraggable(true);
		marker = Marker.getInstance(options);
		marker.setMap(map);

		marker.addClickHandler(new MClickHandler() {
			@Override
			public void onEvent(MClickEvent event) {
				MapHelper.getInstance().createInfoWindow(map, event.getLatLng(), new HTML(txtCurrAddress.getText()));
			}
		});
		marker.addDragEndHandler(new MDragEndHandler() {
			@Override
			public void onEvent(MDragEndEvent event) {
				showPointOnMap(event.getLatLng());
				// MapHelper.getInstance().createInfoWindow(map, event.getLatLng(), new HTML(txtCurrAddress.getText()));
			}
		});
	}

	private void setLatLongInProfile(LatLng point) {
		currProfile.setCurrLatitude(point.lat());
		currProfile.setCurrLongitude(point.lng());
	}

	private void showPointOnMap(final LatLng point) {
		InfoWindow.closeExistingInfoWindow();
		setLatLongInProfile(point);

		// Do the reverse geocoding for finding the address string and other data for that point.
		GeocoderRequest request = GeocoderRequest.newInstance();
		request.setLocation(point);
		Geocoder.newInstance().geocode(request, new GeocoderRequestHandler() {

			@Override
			public void onCallback(JsArray<GeocoderResult> results, GeocoderStatus status) {
				if (status == GeocoderStatus.OK) {
					if (results.length() > 0) {

						// GeocoderResult place = results.get(0);
						FlexTable table = new FlexTable();

						for (int i = 0; i < 2; i++) {
							final GeocoderResult currPlace = results.get(i);
							RadioButton button = new RadioButton("place");
							button.setFormValue(currPlace.getFormatted_Address());
							table.setWidget(i + 1, 0, button);
							table.setWidget(i + 1, 1, new Label(currPlace.getFormatted_Address()));
							button.addClickHandler(new ClickHandler() {
								@Override
								public void onClick(ClickEvent event) {
									String buttonValue = ((RadioButton) event.getSource()).getFormValue();
									String countryLongName = "";
									String countryShortName = "";
									String state = "";
									String city = "";
									JsArray<GeocoderAddressComponent> addressComponents = currPlace.getAddress_Components();
									List<String> possibleOptions = Arrays.asList("country", "administrative_area_level_1", "locality");
									for (int j = 0; j < addressComponents.length(); j++) {
										JsArrayString strType1 = addressComponents.get(j).getTypes();
										String strType = "";
										for (int k = 0; k < strType1.length(); k++) {
											strType = strType1.get(k).toString();
											if (possibleOptions.contains(strType))
												break;
										}
										if ("country" == strType) {
											countryLongName = addressComponents.get(j).getLong_Name();
											countryShortName = addressComponents.get(j).getShort_Name();
										}
										if ("administrative_area_level_1" == strType) {
											state = addressComponents.get(j).getLong_Name();
										}
										if ("locality" == strType) {
											city = addressComponents.get(j).getLong_Name();
										}
									}

									currProfile.setCurrCity(city);
									currProfile.setCurrState(state);
									currProfile.setCurrCountry(countryShortName);
									txtCurrAddress.setText(buttonValue);
									currProfile.setCurrGeoAddress(buttonValue);
									InfoWindow.closeExistingInfoWindow();
								}
							});

						}
						MapHelper.getInstance().createInfoWindow(map, point, table);
					}
				} else {
					showAddressNotFoundDialog();
				}

			}
		});
	}

	private void showAddressNotFoundDialog() {
		UIUtil.showDialog(Arrays.asList("Sorry, we were unable to find that address",
				"Please try to zoom map in the region you live, and see if you can find some road name, area name etc.",
				"Do not add your house number or building number.", "Example: Ghatkopar (E),Mumbai, India or Sneh Nagar, Jabalpur, MP, India."),
				"Error");
	}

	public Widget asWidget() {
		return this;
	}

	public Profile getProfile() {

		List<String> errors = validateProfile();

		if (!errors.isEmpty()) {
			// showDialog(errors, "Please complete following fields");
			return null;
		} else {
			Profile profile = currProfile;
			String hiddenId = hidden.getValue();
			if (!"".equals(hiddenId)) {
				profile.setId(Long.parseLong(hiddenId));
			}

			profile.setName(txtName.getText().trim());
			profile.setGender(rdbtnMale.getValue() ? "Male" : "Female");
			// Date dob = UIUtil.toDate(txtDateBox.getValue().trim());
			Date dob = txtDateBox.getValue();
			profile.setDob(dob);

			long inches = ftInStringToInches(cbHeight.getItemText(cbHeight.getSelectedIndex()));
			profile.setHeight(inches);
			profile.setMaritalStatus(getCBText(cbMaritalStatus));
			if (!"Unmarried".equals(getCBText(cbMaritalStatus))) {
				// profile.setMaritalStatusDetail(txtMaritalStatusDetail.getText());
				String maritalStatusChildren = getCBText(cbMaritalStatusChildren);
				profile.setMaritalStatusChildren(maritalStatusChildren);
			}
			profile.setReligion(getCBText(cbReligion));
			profile.setCaste(casteSuggestBox.getText().trim());
			profile.setMotherTongue(getCBText(cbMotherTongue));
			profile.setLanguages(slLanguageList.getSelectedItems());
			profile.setEatingHabits(getCBText(cbEatingHabits));
			profile.setBloodGroup(getCBText(cbBloodGroup));
			profile.setPhysicalStatus(getCBText(cbPhysicalStatus));
			if (!"Normal".equals(getCBText(cbPhysicalStatus))) {
				profile.setPhysicalStatusDetail(getCBText(cbPhysicalStatusDetail));
			}
			profile.setDegrees(slDegreeList.getSelectedItems());
			profile.setEmploymentType(getCBText(cbEmploymentTypeList));
			profile.setAboutMe(txtAboutMe.getText().trim());
			profile.setSmoking(getChkText(chkSmoking));
			profile.setManglik(getChkText(chkManglik));
			profile.setCurrGeoAddress(txtCurrAddress.getText().trim());
			profile.setFamilyLivingWithMe(getChkText(chkFamilyLivingWithMe));

			return profile;
		}

	}

	private List<String> validateProfile() {
		txtName.removeStyleName("invalidEntry");
		txtDateBox.removeStyleName("invalidEntry");
		cbMaritalStatus.removeStyleName("invalidEntry");
		casteSuggestBox.removeStyleName("invalidEntry");
//		slLanguageList.removeStyleName("invalidEntry");
		slDegreeList.removeStyleName("invalidEntry");
		txtAboutMe.removeStyleName("invalidEntry");
		txtCurrAddress.removeStyleName("invalidEntry");
		// txtFamAddress.removeStyleName("invalidEntry");

		List<String> errors = new ArrayList<String>();
		String name = txtName.getText().trim();
		if ("".equals(name)) {
			txtName.addStyleName("invalidEntry");
			errors.add("Name is empty.");
		}else if(name.length() > 35){
			txtName.addStyleName("invalidEntry");
			errors.add("Name length should not be more than 35 characters.");
		}

		if (txtDateBox.getValue() == null) {
			txtDateBox.addStyleName("invalidEntry");
			errors.add("Date of birth is empty.");
		} else {
			Date date = txtDateBox.getValue();
			if (date == null){
				txtDateBox.addStyleName("invalidEntry");
				errors.add("Date of birth format is not correct. Please use " + Config.DEFAULT_DATE_FORMAT + ", for example " + Config.DEFAULT_DATE);
			}
			Date d = new Date();
			int eighteen = d.getYear() - 18;
			int seventy = d.getYear() - 70;
			d.setYear(eighteen);
			if(date.after(d)){
				txtDateBox.addStyleName("invalidEntry");
				errors.add("Minimum age to create profile is 18 years.");
			}
			d.setYear(seventy);
			if(date.before(d)){
				txtDateBox.addStyleName("invalidEntry");
				errors.add("Maximum age supported by Byahi is 70 years.");
			}
		}

		if ("".equals(casteSuggestBox.getText().trim())) {
			casteSuggestBox.addStyleName("invalidEntry");
			errors.add("Caste is empty.");
		}else{
			String religion = getCBText(cbReligion);
			List<String> result = UIUtil.lists.get(Lists.CASTE).get(religion);
			if(!result.contains(casteSuggestBox.getText().trim())){
				errors.add("Please select caste from the list, or please select 'Others'");
			}
		}
		
		// Languages can be empty
//		if (slLanguageList.getSelectedItems().isEmpty()) {
//			slLanguageList.addStyleName("invalidEntry");
//			errors.add("Please add the languages you can speak.");
//		}
		if (slDegreeList.getSelectedItems().isEmpty()) {
			slDegreeList.addStyleName("invalidEntry");
			errors.add("Please add the degrees you have.");
		}else{
			List<String> result = UIUtil.lists.get(Lists.DEGREES).get("");
			if(!result.containsAll(slDegreeList.getSelectedItems())){
				errors.add("Please select degrees from the list, or please select 'Others'");
			}
		}

		if (txtAboutMe.getText().trim().length() < 100) {
			txtAboutMe.addStyleName("invalidEntry");
			errors.add("Please write something about yourself, at least 100 characters maximum 450 characters.");
		}else if (txtAboutMe.getText().trim().length() > 450) {
			txtAboutMe.addStyleName("invalidEntry");
			errors.add("Please write maximum 450 characters about yourself.");
		}

		if ("".equals(txtCurrAddress.getText().trim())) {
			txtCurrAddress.addStyleName("invalidEntry");
			errors.add("Please provide your current location.");
		}

		if (!errors.isEmpty()) {
			UIUtil.showDialog(errors, "Please complete following fields");
		}

		return errors;
	}

	/**
	 * After photo upload, profile must be refreshed.
	 */
	public void reloadProfile() {
		AppController.get().openMyProfiles();
	}

	public void setProfile(Profile profile) {
		currProfile = profile;
		String profileId = profile.getId() == null ? "" : profile.getId() + "";
		hidden.setValue(profileId);

		txtName.setText(profile.getName());
		if ("Male".equals(profile.getGender())) {
			rdbtnMale.setValue(true);
		} else {
			rdbtnFemale.setValue(true);
		}

		if (profile.getDob() == null) {
			DateTimeFormat format = DateTimeFormat.getFormat(Config.DEFAULT_DATE_FORMAT);
			txtDateBox.setValue(format.parse(Config.DEFAULT_DATE));
		} else {
			txtDateBox.setValue(profile.getDob());
		}

		setListValue(cbHeight, Arrays.asList(inchesToFtInString(profile.getHeight())));
		setListValue(cbMaritalStatus, Arrays.asList(profile.getMaritalStatus()));

		if (!"Unmarried".equals(profile.getMaritalStatus())) {
			setListValue(cbMaritalStatusChildren, Arrays.asList(profile.getMaritalStatusChildren().toString()));
		}
		setMaritalStatusViewState();

		setListValue(cbReligion, Arrays.asList(profile.getReligion()));
		UIUtil.fillCasteSuggestList(casteSuggestBox, getCBText(cbReligion));
		casteSuggestBox.setText(profile.getCaste());
		setListValue(cbMotherTongue, Arrays.asList(profile.getMotherTongue()));
		setListValue(slLanguageList, profile.getLanguages());
		setListValue(cbEatingHabits, Arrays.asList(profile.getEatingHabits()));
		setListValue(cbBloodGroup, Arrays.asList(profile.getBloodGroup()));
		setListValue(cbPhysicalStatus, Arrays.asList(profile.getPhysicalStatus()));

		if (!"Normal".equals(profile.getPhysicalStatus())) {
			setListValue(cbPhysicalStatusDetail, Arrays.asList(profile.getPhysicalStatusDetail()));
		}

		setPhysicalStatusViewState();

		setListValue(slDegreeList, profile.getDegrees());
		setListValue(cbEmploymentTypeList, Arrays.asList(profile.getEmploymentType()));

		txtAboutMe.setText(profile.getAboutMe());
		aboutMeExpl.setText(getAboutMeDescText());

		chkSmoking.setValue("Yes".equals(profile.getSmoking()) ? true : false);
		chkManglik.setValue("Yes".equals(profile.getManglik()) ? true : false);
		// Only valid profiles have this data, new ones don't
		txtCurrAddress.setText(profile.getCurrGeoAddress());

		if (profile.getCurrLatitude() != null && profile.getCurrLongitude() != null) {
			createMarker(LatLng.getInstance(profile.getCurrLatitude(), profile.getCurrLongitude()));
		}

		chkFamilyLivingWithMe.setValue("Yes".equals(profile.getFamilyLivingWithMe()) ? true : false);
		// setFamilyDetails(chkFamilyLivingWithMe.getValue());

		validateProfile();
		// discard list, just to set error style

	}

}